#!/usr/bin/python
"""Intento hacer un programa pyrhon que acepte un como parametro un archivo y me fabrique un tex


    Por ahora solo acepta el nombre del archivo a interpretar y el nombre del output

   Funciona como un pre procesador que reemplaza lineas
"""
import sys

LINE_KINDS = ["unknown", "equalty", "term"]
Dic= {}

options = {
    "--input":"",
    "--output":"",
    "--verbose":0
}

perror = sys.stderr.write

def handleParameter(str=""):
    try:
	i=sys.argv.index(str)
    except ValueError:
	return
    if options.has_key(str):
	if (options[str]!=0):
	    options[str]=sys.argv[i+1]
	else:
	    options[str]=1;
    else:
	perror("Unknown Option :"+str)

for i in options.iterkeys():
    handleParameter(i)

def pverbose(str=""):
    if options["--verbose"]:
	print str

def eqGenerate(source,label=""):
    """genera el codigo latex para escribir una equacion"""
    if label == "":
	return "\\begin{equation}\n\t"+source+"\\end{equation}\n"
    else:
	return "\\begin{equation}\n\\label{"+label+"}\n\t"+source+"\\end{equation}\n"

def isEqualty(source=""):
    """ detecta si la cadena source es una igualdad o no 
	Alacanza en este caso que la cadena contenga un igual
    """
    return ~source.find("=")

def isTerm(source=""):
    """
	Se fija si source es un termino y no una igualdad
	Entonces si encuatra un + es un termino
    """
    #if ~isEqualty(source):
	#return ~source.find("+")
    return ~isEqualty(source)

def identify(source=""):
    """
	Se fija que goma es source
    """
    if isEqualty(source):
	 return "equalty"
    elif isTerm(source):
	return "term"
    else:
	return "unknown"

def member(source="", part=-1):
    """
	devuelve el miembre part de la source
    """
    if part==-1:
	return source.split('=')
    else:
	try:
	    return (source.split('='))[part] 
	except IndexError:
	    perror("Member Index out of range")


def postProces(source,args=[], kind=""): 
    """hace el post proceso
	args[0] es el nombre del comando member,term, etc...
	los otros dependen de cual comando sea como se interpreta
    """
    RESERVED_FUNTIONS = ["member","term", "add", "identify", "write", "define", "asoc", "text", "relate", "replace", "title", "cmd", "con","null"]
   
    #aca tengo que hacer la interpretacion de las funciones
 
    if args[0]==RESERVED_FUNTIONS[0]: #member
        return member(source,int(args[1])) #(source.split('='))[int(args[1])] + "\n"
    elif args[0]==RESERVED_FUNTIONS[1]: #term:[operator]:number
	src = source
	first = src.find("[") #takes [a+b] term like TERM0
	bras = {}
	#if first==(-1):
	#    bras["TERM0"]=src
	#    src = "TERM0"
	i=0
	while (first!=(-1)):
	    i = first+1
	    nest = 1
	    while nest!=0:
		if src[i]=="]":
		    nest=0
		elif src[i]=="[":
		    nest+=1
		i=i+1
	    second = i-1
	    bras["TERM"+str(len(bras))] = src[first+1:second]
	    src = src[0:first] +"TERM"+str(len(bras)-1)+src[second+1:len(src)]
	    first = src.find("[")

	 	
	try:
	    bin_op = args[1]
	    pos = int(args[2])
	except IndexError:
	    bin_op = ""
	    pos = int(args[1])
	try:
	    if bin_op!="":
		#return (source.split(bin_op))[pos] + "\n"
	        src = src.split(bin_op)[pos]
	        out = ""
	        while(src.find("TERM")!=(-1)):
		   for i in range(0,len(bras)):
		      out = src.replace("TERM"+str(i),Interpret(bras["TERM"+str(i)]))
                      src = out.replace("\n","")

		return src #+ "\n"
	    else:
		#return (source[pos]+"\n")
		return bras["TERM"+str(pos)] #+ "\n"
	except IndexError:
	    perror("Term out of range")
    elif args[0]==RESERVED_FUNTIONS[2]: #add:what:[<binary_operator>:where:where_arg_1:where_arg_2:...]
	try:
	    bin_op = args[2]
	except IndexError:
	    bin_op = "+"
	try:
	    where = Interpret(':'.join(args[3:len(args)]))
	    l = source.rstrip('\"')+'.'+where
	    target=Interpret(l) #does not suppourt many commands yet unless you use foo.add:bar:+:cmd(member:1.term:+:0)
	except IndexError:
	    where = ""
	    target=source

	if isEqualty(target):
	    if isEqualty(args[1]):
		out = ""
		list = []
		list.append(member(target,0))
		list.append(bin_op)
		list.append(member(args[1],0))
		list.append("=")
		list.append(member(target,1))
		list.append(bin_op)
		list.append(member(args[1],1))
		out = out.join(list) #+ "\n"
		return out
	    elif isTerm(args[1]):
		out = ""
		list = [args[1],bin_op,member(target,0),"=",args[1],bin_op,member(target,1)]
		out = out.join(list) #+ "\n"
		return out
	else:
	    list=[target,bin_op,args[1]]
	    out = "".join(list).replace("\n","")
	    cm = ".replace:"+target+":"+out
	    l = (source.rstrip("\"")+cm).replace("\n","")
	    out2 = Interpret(l)
	    return out2
    elif args[0]==RESERVED_FUNTIONS[3]: #identify
	return identify(source)
    elif args[0]==RESERVED_FUNTIONS[4]: #write
	return source
    elif args[0]==RESERVED_FUNTIONS[5]: #define
	    Dic[args[1]]=source #notar que si ya existe lo sobre escribe
	    return source
    elif args[0]==RESERVED_FUNTIONS[6]: #asoc
	try:
	    left = args[1]
	    right = args[2]
	except IndexError:
	    left = "["
	    right = "]"
	if isEqualty(source):
	    list = [left,member(source,0),right,"=",left,member(source,1), right]
        else:
	    list = [left,source,right]
	out = ""
	return out.join(list)
    elif args[0]==RESERVED_FUNTIONS[7]: #text, outputs ldirectly to the file
	#texChunks.append(source+"\n")
	return ""
    elif args[0]==RESERVED_FUNTIONS[8]: #relate:what:relation
	try:
            bin_rel = args[2]
        except IndexError:
            bin_rel = "="
	out = source+bin_rel+args[1]
	return out
    elif args[0]==RESERVED_FUNTIONS[9]: #replace:what:forwhat
	return source.replace(args[1],args[2])
    elif args[0]==RESERVED_FUNTIONS[10]: #title:title
	DOC_TILE=args[1]
	return args[1]
    elif args[0]==RESERVED_FUNTIONS[11]: #cmd:cmd1%cmd2:arg1%cmd3, evaluates to a writer command, useful for the  add command
      #commands separed by % instead of .
	return ':'.join(args[1:len(args)]).replace('%','.') 
    elif args[0]==RESERVED_FUNTIONS[12]: #con:next  concatenates the strings
	return source+args[1]
    elif args[0]==RESERVED_FUNTIONS[13]: #null returns ""
	return ""
    elif args[0] in Dic:
	aux=Dic[args[0]]
	aux = aux.replace("ARG_","ARG")
	pverbose("ARG_ Subsitution ->"+aux)
        #aux = aux.replace("replace","r_e_p_l_a_c_e")
	#pverbose("replace Subsitution ->"+aux)
	for i in range(1,len(args)):
	    if args[i][0:3] == "ARG":
		args[i]=args[i].replace("ARG","ARG_")
	    #aux=aux+".replace:ARG"+str(i)+":"+args[i]
	    aux=aux.replace("ARG"+str(i),args[i])
	pverbose("ARGS Subsitution ->"+aux)
        #aux = Interpret(aux)
        #aux = aux.replace("r_e_p_l_a_c_e","replace")
	#pverbose("r_e_p_l_a_c_e Subsitution ->"+aux)
	#return Dic[args[0]]
	return aux
    else:
	return source #si no se que goma hacer devuelvo lo que entra

def Interpret(com="",line=0):
   """
	I will add the ability to recognize the @something" here
	where something may be something=som@ethin"g
	Also this function will handle the raw string
	not splited by '.'
   """
   #search for the outmost @" and stores its interpretation
   # in str sus
   #the final result goes in result
   sus=""
   first= com.find("@") #find the opening
   openings =0;
   pverbose("Interpreting :"+com)
   if (first!=(-1)):
      second = com.find("\"") #find a posible closing "
      if (second<first):
	 perror("ERROR: No maching @ for \" at line " + str(line))
	 return ""
      if (second==(-1)):
	 perror("ERROR: No maching \" for @"+ str(line))
	 return ""
      new_second=second
      openings = com.count('@',first+1,second) # there may be some @'s inside
      while(openings!=0):
	 new_second = com.find('\"',second+1,len(com)) #so i find the next "
	 if (new_second==(-1)):
	    perror("ERROR: No maching \" for @"+ str(line))
	    return ""
	 moitw = com.count('@',second+1,new_second) #more openings in the  way?
	 openings = openings + moitw #i take care of them
	 openings = openings -1; #one by one
	 second = new_second; #actualize the value of the old second

      #sus = Interpret(com[first+1:new_second].rstrip("\""),line) #interprets the @..."
      sus = Interpret(com[first+1:new_second].rstrip(),line) #interprets the @..."
      result = com[0:first]+sus+com[new_second+1:len(com)] #replaces it at result
      result = Interpret(result) # go on interpreting till no more @'s are found
   else:
      result = com

   pverbose ("Interpret - result = " +result)
   idx = result.split('.')
   aux = idx[0]
   for i in range(0,len(idx)):
      args = idx[i].split(':')
      aux = aux.rstrip("\n")
      aux = postProces(aux,args)
   return aux #solo en este caso devulvo lo que salga de la interptetacion
	    

if __name__ == "__main__":
    output = sys.stdout
    input = sys.stdin
    if (options["--input"]):
	input = open(options["--input"],'r')
	pverbose("File To Edit :"+options["--input"] + "\n")
    if (options["--output"]):
	output = open(options["--output"],'w')
	pverbose("File to Output :"+options["--output"]+"\n")

    #
    #Obtenienfo Informacion desde el archivo
    #
    #try to define the document tittle
    line_count = 0;
    line = input.readline()
    while(line):   
        line_count=line_count+1
	if line[0] == '[' : #discarding lots of lines
	    line = line.lstrip('[')
	    square = line[0:line.rfind(']')]
	    line=Interpret(square,line_count)
	output.write(line)
	line = input.readline()
	    
    pverbose (str(Dic))
    output.close()
